package com.jy.rhin.infra.repo.notfication.topic.query;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jy.framework.base.entity.Page;
import com.jy.rhin.domain.notification.topic.entity.TopicDO;
import com.jy.rhin.domain.notification.topic.entity.TopicQueryFilterVO;
import com.jy.rhin.domain.notification.topic.entity.TopicQueryVO;
import com.jy.rhin.facade.infra.controller.notification.assembler.TopicAssembler;
import com.jy.rhin.infra.repo.notfication.topic.mapper.TopicMapper;
import com.jy.rhin.infra.repo.notfication.topic.mapper.TopicPropertiesMapper;
import com.jy.rhin.infra.repo.notfication.topic.mapper.TopicQueryFilterMapper;
import com.jy.rhin.infra.repo.notfication.topic.mapper.TopicQueryMapper;
import com.jy.rhin.infra.repo.notfication.topic.po.TopicPO;
import com.jy.rhin.infra.repo.notfication.topic.po.TopicPropertiesPO;
import com.jy.rhin.infra.repo.notfication.topic.po.TopicQueryFilterPO;
import com.jy.rhin.infra.repo.notfication.topic.po.TopicQueryPO;
import com.jy.rhin.infra.repo.notfication.topic.query.dto.TopicFullInfoDTO;
import com.jy.rhin.sdk.dto.notification.req.TopicExpDto;
import com.jy.rhin.sdk.dto.notification.req.TopicQueryPageReqDto;
import com.jy.rhin.sdk.dto.notification.resp.*;
import com.jy.starter.repository.utils.PageUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description:
 * @Author: lww
 * @Date: 2022/6/29 11:08
 */
@Service
public class TopicQueryHandler {

    @Resource
    TopicMapper topicMapper;
    @Resource
    TopicQueryMapper topicQueryMapper;
    @Resource
    TopicQueryFilterMapper topicQueryFilterMapper;
    @Resource
    TopicPropertiesMapper topicPropertiesMapper;


    /**
     * 分页查询主题列表
     *
     * @param dto
     * @return
     */
    public Page<TopicInfoDto> queryPage(TopicQueryPageReqDto dto) {
        QueryWrapper<Object> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(!StringUtils.isEmpty(dto.getPublisherCode()), "a.publisher_code", dto.getPublisherCode())
                .like(!StringUtils.isEmpty(dto.getTopicName()), "a.topic_name", dto.getTopicName())
                .orderByDesc("a.create_time");
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<Object> page = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(dto.getCurrent().intValue(), dto.getSize().intValue(), true);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<TopicInfoDto> pageResult = topicMapper.queryPage(page, queryWrapper);
        return PageUtils.page(pageResult);
    }

    /**
     * 查询主题详情
     *
     * @param topicId
     * @return
     */
    public TopicDetailDto queryTopicDetail(Long topicId) {
        List<TopicFullInfoDTO> topicDetail = topicMapper.queryTopicDetail(topicId);
        if (CollectionUtils.isEmpty(topicDetail)) {
            return null;
        }
        //从结果集中获取主题部分的字段，构造主题详情中的主题信息
        TopicDetailDto topicDetailDto = topicDetail.get(0).toTopicDetailDto();
        //处理结果集中的预存查询和过滤条件字段
        List<TopicQueryDto> topicQueryList = topicDetail.stream()
                .filter(topicFullInfoDTO -> !StringUtils.isEmpty(topicFullInfoDTO.getQueryExp()))
                .collect(Collectors.collectingAndThen(
                        //根据预存查询条件进行分组，获取每个查询的过滤条件列表，将得到map：key为预存查询，value为对应的过滤条件列表
                        Collectors.groupingBy(TopicFullInfoDTO::toTopicQueryDto, Collectors.mapping(TopicFullInfoDTO::toTopicQueryFilterDto, Collectors.toList())),
                        //将map转成list，得到预存查询列表
                        map -> map.entrySet()
                                .stream()
                                .map(entry -> {
                                    TopicQueryDto topicQueryDto = entry.getKey();
                                    topicQueryDto.setFilters(entry.getValue());
                                    return topicQueryDto;
                                })
                                .collect(Collectors.toList())
                ));
        topicDetailDto.setQueryList(topicQueryList);
        return topicDetailDto;
    }

    /**
     * 根据主题表达式查询主题
     *
     * @param topicExp
     * @return
     */
    public TopicDO queryTopicByExp(String topicExp) {
        QueryWrapper<TopicPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TopicPO::getTopicExp, topicExp);
        TopicPO topicPo = topicMapper.selectOne(queryWrapper);
        return Objects.isNull(topicPo) ? null : topicPo.toDO();
    }

    /**
     * 根据主题表达式和查询函数表达式查询函数
     *
     * @param topicExp
     * @param queryExp
     * @return
     */
    public TopicQueryVO queryTopicQueryByExp(String topicExp, String queryExp) {
        QueryWrapper<TopicQueryPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TopicQueryPO::getTopicExp, topicExp);
        queryWrapper.lambda().eq(TopicQueryPO::getQueryExp, queryExp);
        TopicQueryPO topicQueryPo = topicQueryMapper.selectOne(queryWrapper);
        return Objects.isNull(topicQueryPo) ? null : topicQueryPo.toDO();
    }

    /**
     * 根据主题表达式和查询函数表达式查询过滤条件
     *
     * @param topicExp
     * @param queryExp
     * @return
     */
    public List<TopicQueryFilterVO> queryTopicQueryFilterByExp(String topicExp, String queryExp) {
        QueryWrapper<TopicQueryFilterPO> queryFilterPoWrapper = new QueryWrapper<>();
        queryFilterPoWrapper.lambda().eq(TopicQueryFilterPO::getTopicExp, topicExp);
        queryFilterPoWrapper.lambda().eq(TopicQueryFilterPO::getQueryExp, queryExp);
        List<TopicQueryFilterPO> queryFilterPoList = topicQueryFilterMapper.selectList(queryFilterPoWrapper);
        if (!CollectionUtils.isEmpty(queryFilterPoList)) {
            return queryFilterPoList.stream().map(TopicQueryFilterPO::toDO).collect(Collectors.toList());
        }
        return Collections.emptyList();
    }

    /**
     * 根据主题表达式获取预存函数列表
     *
     * @param dto
     * @return
     */
    public List<TopicQueryDto> queryTopicQueryAndTopicFilterList(TopicExpDto dto) {
        QueryWrapper<TopicQueryPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TopicQueryPO::getTopicExp, dto.getTopicExp());
        List<TopicQueryPO> poList = topicQueryMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(poList)) {
            return Collections.emptyList();
        }
        QueryWrapper<TopicQueryFilterPO> queryFilterPoWrapper = new QueryWrapper<>();
        queryFilterPoWrapper.lambda().eq(TopicQueryFilterPO::getTopicExp, dto.getTopicExp());
        List<TopicQueryFilterPO> queryFilterPoList = topicQueryFilterMapper.selectList(queryFilterPoWrapper);
        Map<String, List<TopicQueryFilterDto>> queryFilterMap = new HashMap<>(16);
        if (!CollectionUtils.isEmpty(queryFilterPoList)) {
            List<TopicQueryFilterDto> queryFilterList = queryFilterPoList.stream().map(TopicAssembler::toQueryFilterDTO).collect(Collectors.toList());
            queryFilterMap = queryFilterList.stream().collect(Collectors.groupingBy(TopicQueryFilterDto::getQueryExp));
        }

        List<TopicQueryDto> resultList = new ArrayList<>();
        for (TopicQueryPO po : poList) {
            TopicQueryDto queryDto = TopicAssembler.toQueryDTO(po);
            queryDto.setFilters(queryFilterMap.get(po.getQueryExp()));
            resultList.add(queryDto);
        }

        return resultList;
    }

    /**
     * 查询主题消息属性字段
     *
     * @param topicExp
     * @return
     */
    public List<TopicPropertiesDto> queryTopicProperties(String topicExp) {
        QueryWrapper<TopicPropertiesPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(TopicPropertiesPO::getTopicExp, topicExp);
        List<TopicPropertiesPO> topicPropertiesPoList = topicPropertiesMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(topicPropertiesPoList)) {
            return Collections.emptyList();
        }
        return topicPropertiesPoList.stream().map(TopicAssembler::toPropertiesDTO).collect(Collectors.toList());
    }

    /**
     * 主题简明信息列表查询
     *
     * @return
     */
    public List<TopicShortDto> queryTopicList() {
        QueryWrapper<TopicPO> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().orderByDesc(TopicPO::getCreateTime);
        List<TopicPO> poList = topicMapper.selectList(queryWrapper);
        if (CollectionUtils.isEmpty(poList)) {
            return Collections.emptyList();
        }
        return poList.stream().map(TopicAssembler::toShortDTO).collect(Collectors.toList());
    }


    /**
     * 统计主题数量
     *
     * @return
     */
    public Integer countTopic() {
        QueryWrapper<TopicPO> queryWrapper = new QueryWrapper<>();
        return topicMapper.selectCount(queryWrapper);
    }

    /**
     * 事件主题订阅数top数
     *
     * @return
     */
    public List<EventTopicListDto> queryEventTopicList(Integer topCount) {
        QueryWrapper<Object> queryWrapper = new QueryWrapper<>();
        queryWrapper.orderByDesc("subscriptions", "a.create_time");
        queryWrapper.last("limit " + topCount);
        return topicMapper.queryEventTopicList(queryWrapper);
    }
}
